package ldh.im.monitor;

import com.dustinredmond.fxtrayicon.FXTrayIcon;
import io.netty.channel.Channel;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import ldh.im.fxbase.InitDb;
import ldh.im.fxbase.util.*;
import ldh.im.monitor.controller.MonitorLoginController;
import ldh.im.monitor.controller.MonitorMainController;
import ldh.im.monitor.rpc.ImCommunicateService;
import ldh.im.monitor.rpc.RpcMonitorLoginService;
import ldh.im.monitor.rpc.RpcMonitorRouter;
import ldh.im.monitor.service.ConnectionCheckService;
import ldh.im.rpc.LoginFilter;
import ldh.im.rpc.LoginSuccessFilter;
import ldh.im.util.ConfigUtil;
import ldh.rpc.RpcConfig;
import ldh.rpc.cache.LocalRpcCacheService;
import ldh.rpc.client.RpcClientBootstrap;
import ldh.rpc.client.RpcClientSocketBootstrap;
import ldh.rpc.listener.ChannelEventType;
import ldh.rpc.listener.ChannelListener;

import java.util.ArrayList;
import java.util.List;

public class MonitorMainApp extends Application implements ChannelListener {

    private RpcClientBootstrap clientBootstrap = null;
    private ConnectionCheckService connectionCheckService = null;

    private InitDb initDb = new MonitorInitDb();

    @Override
    public void start(Stage primaryStage) throws Exception {
        System.setProperty("file.encoding", "GBK");
        StageUtil.setStage(primaryStage);

        initDb.initDb(ConfigUtil.getDataDir());

        initMonitorService();

        showLoginPane(primaryStage);
    }

    private void showLoginPane(Stage primaryStage) {
        RegionUtil.FxmlBean<Pane, MonitorLoginController> fxmlBean = RegionUtil.loadFxmlBean(this.getClass().getResource("/fxml/MonitorLoginPage.fxml"));
        Scene scene = fxmlBean.getController().createScene();

        Stage stage = new Stage();
        stage.getIcons().add(new Image(this.getClass().getResource("/imgs/jg.jpg").toExternalForm()));

        stage.initOwner(primaryStage);
        stage.initStyle(StageStyle.TRANSPARENT);
        stage.setScene(scene);

        stage.show();

        fxmlBean.getController().setLoginStage(stage);
        fxmlBean.getController().setCacheService(clientBootstrap.getRpcConfig().getCacheService());
        fxmlBean.getController().setConsumer((Void) -> {
//            String userId = VarConfig.getValue(ImConfig.LOGIN_USER_ID).toString();
            FxThreadUtil.runLater(() -> showMainPane(primaryStage));
        });
    }

    private void showMainPane(Stage primaryStage) {
        primaryStage.getIcons().add(new Image(this.getClass().getResource("/imgs/jg.jpg").toExternalForm()));

        RegionUtil.FxmlBean<Pane, MonitorMainController> fxmlBean = RegionUtil.loadFxmlBean(this.getClass().getResource("/fxml/MonitorMainPage.fxml"));
        Pane mainPane = fxmlBean.getNode();

        Scene scene = new Scene(mainPane, 900, 650);
        scene.setFill(Color.RED);

        scene.getStylesheets().add(this.getClass().getResource("/css/var.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/stage.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/application.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/scrollbar.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/bootstrapfx.css").toExternalForm());

        primaryStage.setScene(scene);
        primaryStage.initStyle(StageStyle.TRANSPARENT);

        ResizeHelper.addResizeListener(primaryStage);

        FXTrayIcon trayIcon = new FXTrayIcon(primaryStage, getClass().getResource("/imgs/jg.jpg"));
        trayIcon.addExitItem("Exit", e -> {
            Platform.setImplicitExit(true);
            Platform.exit();
            ThreadPoolUtil.close();
            System.exit(0);
        });
        trayIcon.addMenuItems(createTrayMenuItems(primaryStage).toArray(MenuItem[]::new));
        primaryStage.show();
        trayIcon.show();
        primaryStage.toFront();

        primaryStage.maximizedProperty().addListener(l -> {
            if (primaryStage.isMaximized()) {
                mainPane.getStyleClass().add("max-stage");
            } else {
                mainPane.getStyleClass().remove("max-stage");
            }
        });
    }

    private List<MenuItem> createTrayMenuItems(Stage primaryStage) {
        List<MenuItem> menuItems = new ArrayList<>();
        MenuItem openMenuItem = new MenuItem("打开");
        openMenuItem.setOnAction(e -> {
            primaryStage.show();
            primaryStage.toFront();
        });
        menuItems.add(openMenuItem);
        return menuItems;
    }

    private void initMonitorService() throws Exception {
        clientBootstrap = createClientBootstrap();
        RpcUtil.setRpcBootstrap(clientBootstrap);
        clientBootstrap.addRouters(RpcMonitorLoginService.class);
        clientBootstrap.addRouters(RpcMonitorRouter.class);
        clientBootstrap.addFilters(new LoginSuccessFilter(clientBootstrap.getRpcConfig()), new LoginFilter());
        clientBootstrap.start(this);

        RpcUtil.setRpcBootstrap(clientBootstrap);

        connectionCheckService = new ConnectionCheckService(clientBootstrap);
        connectionCheckService.reconnectionCheck();
    }

    protected RpcClientBootstrap createClientBootstrap() throws InterruptedException {
        String address = ConfigUtil.getString("monitor.address");
        int port = ConfigUtil.getInt("monitor.port", 9990);
        RpcConfig rpcConfig = new RpcConfig(new LocalRpcCacheService("monitor"), address, port, "binary");
        rpcConfig.setCommunicateService(new ImCommunicateService(rpcConfig));

        RpcClientBootstrap clientBootstrap = new RpcClientSocketBootstrap(rpcConfig);
        return clientBootstrap;
    }

    @Override
    public void channelEvent(Channel channel, ChannelEventType channelEventType) {
        // todo
    }
}
